﻿using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Activation;
using WCFCollection;
using System.Collections;
using System.Xml.Linq;
using RemoteLinqBase.ServerBase;
using RemoteLinqBase.Model;

namespace RemoteLinqServer
{
	[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service : ICollectionService
    {
		public Service()
		{
			var hotels = RegisterObject<Hotel>();
			hotels.Add(new Hotel
			{
				Name = "Royal Hotel",
				Rooms = new Room[] { 
					new Room { Name = "Small room 1", Beds = 1 },
					new Room { Name = "Medium room 1", Beds = 2, HasToilet = true },
					new Room { Name = "President room 1", Beds = 4, HasToilet = true, HasBathroom = true }
				}
			});
			hotels.Add(new Hotel
			{
				Name = "Small Hotel",
				Rooms = new Room[] { 
					new Room { Name = "Room 1", Beds = 1, HasToilet = true },
					new Room { Name = "Room 2", Beds = 2, HasToilet = true },
					new Room { Name = "Room 3", Beds = 2, HasToilet = true },
					new Room { Name = "Room 4", Beds = 2, HasToilet = true },
					new Room { Name = "Room 5", Beds = 3, HasToilet = true }
				}
			});

			// !!!we will create complete new tree to prevent serialization recursion, please note, that your serialization function need to think about this!!!
			var rooms = RegisterObject<Room>();
			var hotel1 = new Hotel{Name = "Hotel 1"};
			var hotel2 = new Hotel{Name = "Hotel 2"};
			rooms.Add(new Room { Name = "Room 1", Beds = 1, Owner = hotel1 });
			rooms.Add(new Room { Name = "Room 2", Beds = 2, Owner = hotel1, HasToilet = true });
			rooms.Add(new Room { Name = "Room 3", Beds = 2, Owner = hotel1, HasToilet = true, HasBathroom = true });
			rooms.Add(new Room { Name = "Room 4", Beds = 2, Owner = hotel2, HasToilet = true });
			rooms.Add(new Room { Name = "Room 5", Beds = 3, Owner = hotel2, HasToilet = true, HasBathroom = true });
			rooms.Add(new Room { Name = "Another Room 1", Beds = 1, Owner = hotel1 });
			rooms.Add(new Room { Name = "Another Room 2", Beds = 2, Owner = hotel1, HasToilet = true });
			rooms.Add(new Room { Name = "Another Room 3", Beds = 4, Owner = hotel1, HasToilet = true, HasBathroom = true });
			rooms.Add(new Room { Name = "Another Room 4", Beds = 2, Owner = hotel2, HasToilet = true });
			rooms.Add(new Room { Name = "Another Room 5", Beds = 3, Owner = hotel2, HasToilet = true, HasBathroom = true });
		}
		
		/// <summary>
		/// Collection containing connector to generic collections.
		/// </summary>
		Dictionary<string, GenericWrapper<object>> _Connectors = new Dictionary<string, GenericWrapper<object>>();
		public Dictionary<string, GenericWrapper<object>> Connectors
		{
			get
			{
				return _Connectors;
			}
		}


		/// <summary>
		/// Registers the object.
		/// </summary>
		/// <typeparam name="TType">The type of the type.</typeparam>
		/// <param name="getItemId">The get item id.</param>
		protected GenericCollection<TType> RegisterObject<TType>() where TType : class
		{
            SerializationTool.AddNewRegisteredType(typeof(TType));
			GenericCollection<TType> result = new GenericCollection<TType>();
			// add connector
			_Connectors.Add(typeof(TType).Name, GenericWrapper<object>.GetWrapper(result));
			return result;
		}
		/// <summary>
		/// Gets the result of linq in XML.
		/// </summary>
		/// <param name="collection">The collection.</param>
		/// <param name="linq">The linq.</param>
		/// <returns>Result of linq query.</returns>
		public XElement GetResultLinqInXml(string collection, string linq)
		{
			return SerializationTool.CollectionToXML(HandleGetResultLinq(_Connectors[collection], linq), collection);
		}

		/// <summary>
		/// Handles the get result of linq.
		/// </summary>
		/// <param name="connector">The connector.</param>
		/// <param name="linq">The linq.</param>
		/// <returns>Result of linq query.</returns>
		object HandleGetResultLinq(GenericWrapper<object> connector, string linq)
		{
			return connector.GetResultLinq(linq);
		}
    }
}
